home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_147 / src / random.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  440 lines

  1. /*
  2.  *        Assorted commands.
  3.  * The file contains the command
  4.  * processors for a large assortment of unrelated
  5.  * commands. The only thing they have in common is
  6.  * that they are all command processors.
  7.  */
  8. #include    "def.h"
  9.  
  10. /*
  11.  * Display a bunch of useful information about
  12.  * the current location of dot. The character under the
  13.  * cursor (in octal), the current line, row, and column, and
  14.  * approximate position of the cursor in the file (as a percentage)
  15.  * is displayed. The column position assumes an infinite position
  16.  * display; it does not truncate just because the screen does.
  17.  * This is normally bound to "C-X =".
  18.  */
  19. /*ARGSUSED*/
  20. showcpos(f, n)
  21. {
  22.     register LINE    *clp;
  23.     register long    nchar;
  24.     long        cchar;
  25.     register int    nline, row;
  26.     int        cline, cbyte;    /* Current line/char/byte */
  27.     int        ratio;
  28.  
  29.     clp = lforw(curbp->b_linep);        /* Collect the data.    */
  30.     nchar = 0;
  31.     nline = 0;
  32.     for (;;) {
  33.         ++nline;            /* Count this line    */
  34.         if (clp == curwp->w_dotp) {
  35.             cline = nline;        /* Mark line        */
  36.             cchar = nchar + curwp->w_doto;
  37.             if (curwp->w_doto == llength(clp))
  38.                 cbyte = '\n';
  39.             else
  40.                 cbyte = lgetc(clp, curwp->w_doto);
  41.         }
  42.         nchar += llength(clp);        /* Now count the chars    */
  43.         clp = lforw(clp);
  44.         if (clp == curbp->b_linep) break;
  45.         nchar++;            /* count the newline    */
  46.     }
  47.     row = curwp->w_toprow + 1;        /* Determine row.    */
  48.     clp = curwp->w_linep;
  49.     while (clp!=curbp->b_linep && clp!=curwp->w_dotp) {
  50.         ++row;
  51.         clp = lforw(clp);
  52.     }
  53.     /*NOSTRICT*/
  54.     ratio = nchar ? (100L*cchar) / nchar : 100;
  55.     ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",
  56.         cbyte, cbyte, cchar, ratio, cline, row, getcolpos());
  57.     return TRUE;
  58. }
  59.  
  60. getcolpos() {
  61.     register int    col, i, c;
  62.  
  63.     col = 1;                /* Determine column.    */
  64.     for (i=0; i<curwp->w_doto; ++i) {
  65.         c = lgetc(curwp->w_dotp, i);
  66.         if (c == '\t'
  67. #ifdef    NOTAB
  68.             && !(curbp->b_flag & BFNOTAB)
  69. #endif
  70.             ) {
  71.             col |= 0x07;
  72.             ++col;
  73.         } else if (ISCTRL(c) != FALSE)
  74.             ++col;
  75.         ++col;
  76.     }
  77.     return col;
  78. }
  79. /*
  80.  * Twiddle the two characters on either side of
  81.  * dot. If dot is at the end of the line twiddle the
  82.  * two characters before it. Return with an error if dot
  83.  * is at the beginning of line; it seems to be a bit
  84.  * pointless to make this work. This fixes up a very
  85.  * common typo with a single stroke. Normally bound
  86.  * to "C-T". This always works within a line, so
  87.  * "WFEDIT" is good enough.
  88.  */
  89. /*ARGSUSED*/
  90. twiddle(f, n)
  91. {
  92.     register LINE    *dotp;
  93.     register int    doto;
  94.     register int    cr;
  95.     VOID     lchange();
  96.  
  97.     dotp = curwp->w_dotp;
  98.     doto = curwp->w_doto;
  99.     if(doto==llength(dotp)) {
  100.         if(--doto<=0) return FALSE;
  101.     } else {
  102.         if(doto==0) return FALSE;
  103.         ++curwp->w_doto;
  104.     }
  105.     cr = lgetc(dotp, doto--);
  106.     lputc(dotp, doto+1, lgetc(dotp, doto));
  107.     lputc(dotp, doto, cr);
  108.     lchange(WFEDIT);
  109.     return TRUE;
  110. }
  111.  
  112. /*
  113.  * Open up some blank space. The basic plan
  114.  * is to insert a bunch of newlines, and then back
  115.  * up over them. Everything is done by the subcommand
  116.  * procerssors. They even handle the looping. Normally
  117.  * this is bound to "C-O".
  118.  */
  119. /*ARGSUSED*/
  120. openline(f, n)
  121. {
  122.     register int    i;
  123.     register int    s;
  124.  
  125.     if (n < 0)
  126.         return FALSE;
  127.     if (n == 0)
  128.         return TRUE;
  129.     i = n;                    /* Insert newlines.    */
  130.     do {
  131.         s = lnewline();
  132.     } while (s==TRUE && --i);
  133.     if (s == TRUE)                /* Then back up overtop */
  134.         s = backchar(f | FFRAND, n);    /* of them all.        */
  135.     return s;
  136. }
  137.  
  138. /*
  139.  * Insert a newline.
  140.  * If you are at the end of the line and the
  141.  * next line is a blank line, just move into the
  142.  * blank line. This makes "C-O" and "C-X C-O" work
  143.  * nicely, and reduces the ammount of screen
  144.  * update that has to be done. This would not be
  145.  * as critical if screen update were a lot
  146.  * more efficient.
  147.  */
  148. /*ARGSUSED*/
  149. newline(f, n)
  150. {
  151.     register LINE    *lp;
  152.     register int    s;
  153.  
  154.     if (n < 0) return FALSE;
  155.     while (n--) {
  156.         lp = curwp->w_dotp;
  157.         if (llength(lp) == curwp->w_doto
  158.         && lforw(lp) != curbp->b_linep
  159.         && llength(lforw(lp)) == 0) {
  160.             if ((s=forwchar(FFRAND, 1)) != TRUE)
  161.                 return s;
  162.         } else if ((s=lnewline()) != TRUE)
  163.             return s;
  164.     }
  165.     return TRUE;
  166. }
  167.  
  168. /*
  169.  * Delete blank lines around dot.
  170.  * What this command does depends if dot is
  171.  * sitting on a blank line. If dot is sitting on a
  172.  * blank line, this command deletes all the blank lines
  173.  * above and below the current line. If it is sitting
  174.  * on a non blank line then it deletes all of the
  175.  * blank lines after the line. Normally this command
  176.  * is bound to "C-X C-O". Any argument is ignored.
  177.  */
  178. /*ARGSUSED*/
  179. deblank(f, n)
  180. {
  181.     register LINE    *lp1;
  182.     register LINE    *lp2;
  183.     register RSIZE    nld;
  184.  
  185.     lp1 = curwp->w_dotp;
  186.     while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  187.         lp1 = lp2;
  188.     lp2 = lp1;
  189.     nld = (RSIZE) 0;
  190.     while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  191.         ++nld;
  192.     if (nld == 0)
  193.         return (TRUE);
  194.     curwp->w_dotp = lforw(lp1);
  195.     curwp->w_doto = 0;
  196.     return ldelete((RSIZE)nld, KNONE);
  197. }
  198.  
  199. /*
  200.  * Delete any whitespace around dot, then insert a space.
  201.  */
  202. justone(f, n) {
  203.     (VOID) delwhite(f, n);
  204.     return linsert(1, ' ');
  205. }
  206. /*
  207.  * Delete any whitespace around dot.
  208.  */
  209. /*ARGSUSED*/
  210. delwhite(f, n)
  211. {
  212.     register int    col, c, s;
  213.  
  214.     col = curwp->w_doto;
  215.     while (((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
  216.             && col < llength(curwp->w_dotp))
  217.         ++col;
  218.     do {
  219.         if (curwp->w_doto == 0) {
  220.             s = FALSE;
  221.             break;
  222.         }
  223.         if ((s = backchar(FFRAND, 1)) != TRUE) break;
  224.     } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t');
  225.  
  226.     if (s == TRUE) (VOID) forwchar(FFRAND, 1);
  227.     (VOID) ldelete((RSIZE)(col - curwp->w_doto), KNONE);
  228.     return TRUE;
  229. }
  230. /*
  231.  * Insert a newline, then enough
  232.  * tabs and spaces to duplicate the indentation
  233.  * of the previous line. Assumes tabs are every eight
  234.  * characters. Quite simple. Figure out the indentation
  235.  * of the current line. Insert a newline by calling
  236.  * the standard routine. Insert the indentation by
  237.  * inserting the right number of tabs and spaces.
  238.  * Return TRUE if all ok. Return FALSE if one
  239.  * of the subcomands failed. Normally bound
  240.  * to "C-J".
  241.  */
  242. /*ARGSUSED*/
  243. indent(f, n)
  244. {
  245.     register int    nicol;
  246.     register int    c;
  247.     register int    i;
  248.  
  249.     if (n < 0) return (FALSE);
  250.     while (n--) {
  251.         nicol = 0;
  252.         for (i=0; i<llength(curwp->w_dotp); ++i) {
  253.             c = lgetc(curwp->w_dotp, i);
  254.             if (c!=' ' && c!='\t')
  255.                 break;
  256.             if (c == '\t')
  257.                 nicol |= 0x07;
  258.             ++nicol;
  259.         }
  260.         if (lnewline() == FALSE || ((
  261. #ifdef    NOTAB
  262.             curbp->b_flag&BFNOTAB) ?
  263.             linsert(nicol, ' ') == FALSE : (
  264. #endif
  265.             ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE) ||
  266.             ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))))
  267.             return FALSE;
  268.     }
  269.     return TRUE;
  270. }
  271.  
  272. /*
  273.  * Delete forward. This is real
  274.  * easy, because the basic delete routine does
  275.  * all of the work. Watches for negative arguments,
  276.  * and does the right thing. If any argument is
  277.  * present, it kills rather than deletes, to prevent
  278.  * loss of text if typed with a big argument.
  279.  * Normally bound to "C-D".
  280.  */
  281. /*ARGSUSED*/
  282. forwdel(f, n)
  283. {
  284.     if (n < 0)
  285.         return backdel(f | FFRAND, -n);
  286.     if (f & FFARG) {            /* Really a kill.    */
  287.         if ((lastflag&CFKILL) == 0)
  288.             kdelete();
  289.         thisflag |= CFKILL;
  290.     }
  291.     return ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);
  292. }
  293.  
  294. /*
  295.  * Delete backwards. This is quite easy too,
  296.  * because it's all done with other functions. Just
  297.  * move the cursor back, and delete forwards.
  298.  * Like delete forward, this actually does a kill
  299.  * if presented with an argument.
  300.  */
  301. /*ARGSUSED*/
  302. backdel(f, n)
  303. {
  304.     register int    s;
  305.  
  306.     if (n < 0)
  307.         return forwdel(f | FFRAND, -n);
  308.     if (f & FFARG) {            /* Really a kill.    */
  309.         if ((lastflag&CFKILL) == 0)
  310.             kdelete();
  311.         thisflag |= CFKILL;
  312.     }
  313.     if ((s=backchar(f | FFRAND, n)) == TRUE)
  314.         s = ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);
  315.     return s;
  316. }
  317.  
  318. /*
  319.  * Kill line. If called without an argument,
  320.  * it kills from dot to the end of the line, unless it
  321.  * is at the end of the line, when it kills the newline.
  322.  * If called with an argument of 0, it kills from the
  323.  * start of the line to dot. If called with a positive
  324.  * argument, it kills from dot forward over that number
  325.  * of newlines. If called with a negative argument it
  326.  * kills any text before dot on the current line,
  327.  * then it kills back abs(arg) lines.
  328.  */
  329. /*ARGSUSED*/
  330. killline(f, n) {
  331.     register RSIZE    chunk;
  332.     register LINE    *nextp;
  333.     register int    i, c;
  334.     VOID     kdelete();
  335.  
  336.     if ((lastflag&CFKILL) == 0)        /* Clear kill buffer if */
  337.         kdelete();            /* last wasn't a kill.    */
  338.     thisflag |= CFKILL;
  339.     if (!(f & FFARG)) {
  340.         for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
  341.             if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
  342.                 break;
  343.         if (i == llength(curwp->w_dotp))
  344.             chunk = llength(curwp->w_dotp)-curwp->w_doto + 1;
  345.         else {
  346.             chunk = llength(curwp->w_dotp)-curwp->w_doto;
  347.             if (chunk == 0)
  348.                 chunk = 1;
  349.         }
  350.     } else if (n > 0) {
  351.         chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  352.         nextp = lforw(curwp->w_dotp);
  353.         i = n;
  354.         while (--i) {
  355.             if (nextp == curbp->b_linep)
  356.                 break;
  357.             chunk += llength(nextp)+1;
  358.             nextp = lforw(nextp);
  359.         }
  360.     } else {                /* n <= 0        */
  361.         chunk = curwp->w_doto;
  362.         curwp->w_doto = 0;
  363.         i = n;
  364.         while (i++) {
  365.             if (lback(curwp->w_dotp) == curbp->b_linep)
  366.                 break;
  367.             curwp->w_dotp = lback(curwp->w_dotp);
  368.             curwp->w_flag |= WFMOVE;
  369.             chunk += llength(curwp->w_dotp)+1;
  370.         }
  371.     }
  372.     /*
  373.      * KFORW here is a bug. Should be KBACK/KFORW, but we need to
  374.      * rewrite the ldelete code (later)?
  375.      */
  376.     return (ldelete(chunk,    KFORW));
  377. }
  378.  
  379. /*
  380.  * Yank text back from the kill buffer. This
  381.  * is really easy. All of the work is done by the
  382.  * standard insert routines. All you do is run the loop,
  383.  * and check for errors. The blank
  384.  * lines are inserted with a call to "newline"
  385.  * instead of a call to "lnewline" so that the magic
  386.  * stuff that happens when you type a carriage
  387.  * return also happens when a carriage return is
  388.  * yanked back from the kill buffer.
  389.  * An attempt has been made to fix the cosmetic bug
  390.  * associated with a yank when dot is on the top line of
  391.  * the window (nothing moves, because all of the new
  392.  * text landed off screen).
  393.  */
  394. /*ARGSUSED*/
  395. yank(f, n)
  396. {
  397.     register int    c;
  398.     register int    i;
  399.     register LINE    *lp;
  400.     register int    nline;
  401.     VOID     isetmark();
  402.  
  403.     if (n < 0) return FALSE;
  404.     nline = 0;                /* Newline counting.    */
  405.     while (n--) {
  406.         isetmark();            /* mark around last yank */
  407.         i = 0;
  408.         while ((c=kremove(i)) >= 0) {
  409.             if (c == '\n') {
  410.                 if (newline(FFRAND, 1) == FALSE)
  411.                     return FALSE;
  412.                 ++nline;
  413.             } else {
  414.                 if (linsert(1, c) == FALSE)
  415.                     return FALSE;
  416.             }
  417.             ++i;
  418.         }
  419.     }
  420.     lp = curwp->w_linep;            /* Cosmetic adjustment    */
  421.     if (curwp->w_dotp == lp) {        /* if offscreen insert. */
  422.         while (nline-- && lback(lp)!=curbp->b_linep)
  423.             lp = lback(lp);
  424.         curwp->w_linep = lp;        /* Adjust framing.    */
  425.         curwp->w_flag |= WFHARD;
  426.     }
  427.     return TRUE;
  428. }
  429.  
  430. #ifdef    NOTAB
  431. /*ARGSUSED*/
  432. space_to_tabstop(f, n)
  433. int f, n;
  434. {
  435.     if(n<0) return FALSE;
  436.     if(n==0) return TRUE;
  437.     return linsert((n<<3) - (curwp->w_doto & 7), ' ');
  438. }
  439. #endif
  440.